package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.vo.OrganizationVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.ServiceInventoryMapper;
import com.eastfair.venueservice.dto.ServiceInventoryInFlowDTO;
import com.eastfair.venueservice.dto.ServiceInventoryQuery;
import com.eastfair.venueservice.entity.ServiceInventory;
import com.eastfair.venueservice.enumeration.ServiceInventoryInFlowInStockTypeEnum;
import com.eastfair.venueservice.enumeration.ServiceItemServiceStateEnum;
import com.eastfair.venueservice.service.ServiceInventoryInFlowService;
import com.eastfair.venueservice.service.ServiceInventoryService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.venueservice.service.ServiceProviderService;
import com.eastfair.venueservice.vo.ServiceInventoryVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 业务实现类
 * 服务库存
 * </p>
 *
 * @author linan
 * @date 2022-07-14
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceInventoryServiceImpl extends SuperServiceImpl<ServiceInventoryMapper, ServiceInventory> implements ServiceInventoryService {

    @Resource
    private ServiceInventoryInFlowService serviceInventoryInFlowService;
    @Resource
    private AuthServiceFeign authServiceFeign;
    @Resource
    private ServiceProviderService serviceProviderService;
    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceInventory> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }


    @Override
    protected R<Boolean> handlerSave(ServiceInventory model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        return R.successDef();
    }


    @Override
    public void addInventory(String inventoryCode, BigDecimal inNum){
        baseMapper.addInventory(inventoryCode,inNum);
    }

    @Override
    public void minusInventory(String inventoryCode, BigDecimal outNum) {
        baseMapper.minusInventory(inventoryCode,outNum);
    }

    @Override
    public Page<ServiceInventoryVO> queryInventoryList(PageParams<ServiceInventoryQuery> serviceInventoryQuery) {
        serviceInventoryQuery.setSort(null);
        serviceInventoryQuery.setOrder(null);
        Page<ServiceInventoryQuery> serviceInventoryQueryPage=serviceInventoryQuery.buildPage();
        ServiceInventoryQuery model = serviceInventoryQuery.getModel();
        QueryWrapper<ServiceInventory> wrapper = new QueryWrapper<>();
        String serviceProviderType = model.getServiceProviderType();
        wrapper.eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled",BusinessConstant.YES)
                .eq("b.service_state", ServiceItemServiceStateEnum.ON_SHELVES)
                .like(Strings.isNotBlank(model.getServiceName()),"b.service_name",model.getServiceName())
                .like(Strings.isNotBlank(model.getServiceSpecsName()),"d.service_specs_name",model.getServiceSpecsName())
                .eq(Objects.nonNull(model.getServiceCategoryId()),"a.service_category_id",model.getServiceCategoryId())
                .ge(Objects.nonNull(model.getCreateTimeStart()), "a.create_time", model.getCreateTimeStart())
                .le(Objects.nonNull(model.getCreateTimeEnd()), "a.create_time", model.getCreateTimeEnd())
                .eq(Objects.nonNull(model.getServiceProviderType()), "b.service_provider_type", model.getServiceProviderType())
                .eq(Objects.nonNull(model.getServiceProviderId()), "b.service_provider_id", model.getServiceProviderId())
                .eq(Objects.nonNull(model.getExhibitionManageId()), "b.exhibition_manage_id", model.getExhibitionManageId())
                .orderByDesc("create_time");
        if(Strings.isBlank(serviceProviderType)){
            // 场馆查询
            String keyword = StringUtils.isNotBlank(model.getKeyword()) ? model.getKeyword() : Strings.EMPTY;
            // 查询所有部门
            List<OrganizationVo> data = authServiceFeign.queryList(Collections.emptyList()).getData();
            Map<Long, String> orgMap = data.stream().filter(e -> e.getName().contains(keyword)).collect(Collectors.toMap(OrganizationVo::getId, OrganizationVo::getName));
            Set<Long> orgIds = orgMap.keySet();
            List<ServiceProviderVO> serviceProviderVOS = serviceProviderService.listServiceProviderByIds(Collections.emptyList());
            Map<Long, String> serviceProviders = serviceProviderVOS.stream().filter(e -> e.getCompanyName().contains(keyword)).collect(Collectors.toMap(ServiceProviderVO::getId, ServiceProviderVO::getCompanyName));
            Set<Long> providers =serviceProviders.keySet();
            wrapper.eq("b.service_provider_type", DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
            if (StringUtils.isNotBlank(keyword)) {
                wrapper.and(e -> e.or(f -> f.like(StringUtils.isNotBlank(keyword), "b.service_name", model.getKeyword()))
                        .or(StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(orgIds), f -> f.in("b.service_provider_id", orgIds))
                        .or(StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(providers), f -> f.in("b.service_provider_id", providers)));
            }
            Page<ServiceInventoryVO> serviceInventoryVOPage = baseMapper.queryInventoryList(serviceInventoryQueryPage, wrapper);
            for (ServiceInventoryVO record : serviceInventoryVOPage.getRecords()) {
                record.setServiceProviderName(Strings.isNotBlank(orgMap.get(record.getServiceProviderId()))? orgMap.get(record.getServiceProviderId()):serviceProviders.get(record.getServiceProviderId()));
            }
            return serviceInventoryVOPage;
        }else {
            // 主场查询
            wrapper.eq("b.service_provider_type", DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
            return baseMapper.queryInventoryList(serviceInventoryQueryPage, wrapper);
        }
    }

    @Override
    public Map<String, Object> queryInventoryStatistics(ServiceInventoryQuery serviceInventoryQuery) {
        // 库存量 入库量 出库量
        List<Map<String, Object>> inventoryStatistics = baseMapper.queryInventoryStatistics(serviceInventoryQuery);
        // 出入库数量趋势
        List<Map<String, Object>> inOutTrend = baseMapper.inOutTrend(serviceInventoryQuery);
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusDays(6);
        List<LocalDate> betweenDate = getBetweenDate(startDate, now);
        List<Map<String, Object>> trendResult = new ArrayList<>();
        for (LocalDate localDate : betweenDate) {
            boolean flag = false;
            for (Map<String, Object> map : inOutTrend) {
                LocalDate returnDate = LocalDate.parse(map.get("createDate").toString());
                if (localDate.compareTo(returnDate) == 0) {
                    trendResult.add(map);
                    flag = true;
                    break;
                }
            }
            if (flag) {
                continue;
            }
            HashMap<String, Object> zeroMap = new HashMap<>(8);
            zeroMap.put("createDate", localDate);
            zeroMap.put("inNum", 0);
            zeroMap.put("outNum", 0);
            trendResult.add(zeroMap);
        }
        // 库存商品类型数量
        List<Map<String, Object>> inventoryTypeNum = baseMapper.inventoryTypeNum(serviceInventoryQuery);
        // 出库类型数量
        List<Map<String, Object>> inventoryTypeOfOut = baseMapper.inventoryTypeOfOut(serviceInventoryQuery);
        // 入库类型数量
        List<Map<String, Object>> inventoryTypeOfIn = baseMapper.inventoryTypeOfIn(serviceInventoryQuery);
        Map<String, Object> resultMap = new HashMap<>(8);
        for (Map<String, Object> inventoryStatistic : inventoryStatistics) {
            resultMap.put(inventoryStatistic.get("item").toString(),inventoryStatistic.get("num"));
        }
        resultMap.put("inOutTrend",trendResult);
        resultMap.put("inventoryTypeNum",inventoryTypeNum);
        resultMap.put("inventoryTypeOfOut",inventoryTypeOfOut);
        resultMap.put("inventoryTypeOfIn",inventoryTypeOfIn);
        return resultMap;
    }

    @Override
    public List<ServiceInventoryVO> queryWaringItem(Long exhibitionManageId) {
        return baseMapper.queryWaringItem(exhibitionManageId);
    }

    /**
     * 获取一段时间的每一天日期或者月份
     * 开始时间要小于结束时间  时间格式  日 2022-06-12   月 2022-06
     * @param startDate
     * @param endDate
     * @return
     * @throws Exception
     */

    public List<LocalDate> getBetweenDate(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> list = new ArrayList<>();
        long distance = ChronoUnit.DAYS.between(startDate, endDate);
        Stream.iterate(startDate, d -> d.plusDays(1)).limit(distance + 1).forEach(list::add);
        return list;
    }
}
